<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>home</title>
    <link rel="stylesheet" th:href="@{/static/lib/layui-v2.5.4/css/layui.css}" media="all">
    <script>
        const PATH = "[[${#httpServletRequest.getContextPath()}]]";
    </script>

    <!-- 避免Thymeleaf异常 -->
    <script type="text/javascript" th:inline="javascript"></script>

    <script type="text/html" id="control">
        <a class="layui-btn layui-btn-xs" lay-event="detail">详情</a>
    </script>

    <script type="text/html" id="control2">
        <a class="layui-btn layui-btn-xs" lay-event="detail">详情</a>
    </script>
</head>
<body id="iosiframe">

<div id='head_div'>
    <input class="layui-hide" id="environment" value="ENVIRONMENT_ALL">
    <button class="open-all layui-hide"></button>
    <div class="layui-form layui-form-pane" action="" onsubmit="return false">
        <div class="layui-form-item">
            <label class="layui-form-label" title="起始时间"><span style="color:red;">*</span>起始时间</label>
            <div class="layui-input-block">
                <input type="text" id="time" class="layui-input" onchange="getEnv();">
            </div>
        </div>

        <div class="layui-form-item">

            <div class="layui-inline">
                <label class="layui-form-label" title="服务主机名" style="padding: 8px 0;">服务主机名</label>
                <div class="layui-input-inline">
                    <select id="host">
                        <option value="">请选择服务主机名</option>
                    </select>
                </div>
            </div>

            <div class="layui-inline">
                <label class="layui-form-label" title="交易结果状态码">交易结果</label>
                <div class="layui-input-inline">
                    <select id="transactionResult">
                        <option value="">请选择交易结果</option>
                    </select>
                </div>
            </div>

        </div>
    </div>

    <div class="layui-btn-group">
        <button class="layui-btn layui-btn2" id="search" onclick="showData(1)">搜索</button>
    </div>
</div>
<div id='body_div'>
    <div id="left" style="width:59.9%;float:left;">
        <table class="layui-table" id='data-table' lay-filter="control"></table>
    </div>
    <div style="width:39.4%;height:100%;float:left;margin-left:0.5%;overflow: auto;margin-top:-50px;">
        <p id="info" style="line-height:20px;"></p>
        <table class="layui-table" id='data-table2' lay-size="sm" lay-filter="control2"></table>
    </div>
</div>

<script src="/static/layui/layui.all.js" th:src="@{/static/lib/layui-v2.5.4/layui.all.js}"></script>
<script th:src="@{/static/lib/jquery-3.4.1/jquery-3.4.1.min.js}"></script>
<script src="/static/js/lay-config.js" th:src="@{/static/js/lay-config.js}"></script>
<script>
    let table, form, layer, laydate, tableHeight = 100, treeTable;
    layui.use(['layer', 'table', 'form', 'laydate', 'treeTable'], function () {
        table = layui.table, form = layui.form, layer = layui.layer, laydate = layui.laydate, treeTable = layui.treeTable;
        laydate.render({
            elem: '#time'
            , type: 'datetime'
            , range: true
            , format: 'yyyy-MM-dd HH:mm:ss'
            , done: function (time) {
                if (time === '') {
                    return false;
                }
                let start, end;

                time = time.split(' - ');
                if (time != null && time.length === 2) {
                    start = time[0].replace(' ', 'T') + '.000Z';
                    end = time[1].replace(' ', 'T') + '.000Z';
                }
                $.post({
                    url: '/services/getEnv',
                    data: {
                        start: encodeURIComponent(start),
                        end: encodeURIComponent(end)
                    },
                    success: function (res) {
                        if (res.success) {
                            $("#environment").html("<option value='ENVIRONMENT_ALL'>ALL</option>");
                            let data = res.data;
                            data = data.replace('[', '').replace(']', '').replaceAll('\"', '').replaceAll('\'', '');
                            data = data.split(',');
                            if (data.length > 0) {
                                for (let i in data) {
                                    if (data.hasOwnProperty(i)) {
                                        $("#environment").append(new Option(data[i], data[i]));
                                    }
                                }
                                getParam();
                            }
                            form.render();
                        }
                    }
                });
            }
        });
    });
    Date.prototype.format = function (fmt) {
        var o = {
            "M+": this.getMonth() + 1, //月份
            "d+": this.getDate(), //日
            "h+": this.getHours(), //小时
            "m+": this.getMinutes(), //分
            "s+": this.getSeconds(), //秒
            "q+": Math.floor((this.getMonth() + 3) / 3), //季度
            "S": this.getMilliseconds() //毫秒
        };
        if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
        for (var k in o)
            if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
        return fmt;
    }
</script>
<script type="text/javascript" th:inline="none">
    let re;

    function showData() {
        init();
        let time = $("#time").val();
        if (time === '') {
            layer.msg('请选择起始时间!', {icon: 2});
            return false;
        }
        let start, end;
        time = time.split(' - ');
        if (time != null && time.length === 2) {
            start = time[0].replace(' ', 'T') + '.000Z';
            end = time[1].replace(' ', 'T') + '.000Z';
        }

        let host = $("#host").val();
        let transactionResult = $("#transactionResult").val();
        let environment = $("#environment").val();

        let hosts = [];
        hosts.push(host);
        let transactionResults = [];
        transactionResults.push(transactionResult);
        let uiFilters = {
            environment: environment
        };

        if (host !== '') {
            uiFilters['host'] = hosts;
        }

        if (transactionResult !== '') {
            uiFilters['transactionResult'] = transactionResults;
        }
        $.post({
            url: '/traces/list',
            data: {
                start: encodeURIComponent(start),
                end: encodeURIComponent(end),
                uiFilters: encodeURIComponent(JSON.stringify(uiFilters))
            },
            success: function (res) {
                let data = [];
                if (res.success) {
                    if (res.data.items === '') {
                        data = [];
                    } else {
                        data = res.data.items;
                    }
                }
                buildTable(data);
                buildTable2([]);
            }
        });
    }

    function buildTable(data) {
        table.render({
            elem: '#data-table',
            data: data,
            cellMinWidth: 80,
            height: tableHeight,
            totalRow: false,
            cols: [[
                /*{
                    field: '', title: '#', align: 'center', width: 110, sort: false, templet: function (r) {
                        return r.LAY_INDEX;
                    }
                },*/
                {field: 'transactionName', title: '接口名称', align: 'center', cellMinWidth: 300, sort: true, fixed: 'left'}
                , {field: 'serviceName', title: '应用名称', align: 'center', width: 125, sort: true}
                , {
                    field: '',
                    title: '延迟(平均值)',
                    align: 'center',
                    cellMinWidth: 140,
                    sort: true,
                    templet: function (r) {
                        return (Number(r['averageResponseTime']) / 1000).toFixed(1) + ' ms';
                    }
                }, {
                    field: '',
                    title: '吞吐量(平均值)',
                    cellMinWidth: 150,
                    align: 'center',
                    sort: true,
                    templet: function (r) {
                        let val = Number(r['transactionsPerMinute']).toFixed(6);
                        if (Number(fix(val, 2)) < 0.1) {
                            return "< 0.1 tpm";
                        } else {
                            return fix(val, 2) + " tpm";
                        }
                    }
                }
                , {
                    field: 'impact',
                    title: '使用率',
                    align: 'center',
                    cellMinWidth: 125,
                    sort: true,
                    templet: function (r) {
                        return (Number(r['impact'])).toFixed(2) + '%';
                    }
                }
                , {
                    field: 'control',
                    fixed: "right",
                    unresize: true,
                    width: 70,
                    title: "操作",
                    align: "center",
                    toolbar: "#control"
                }
            ]],
            id: 'data-table',
            page: true,
            limits: [15, 30, 50, 100],
            limit: 15,
            even: true,
            done: function () {
                bindClick();
            }
        });
    }

    function buildTable2(data) {
        re = treeTable.render({
            elem: '#data-table2',
            id: '#data-table2',
            data: data,
            icon_key: 'title',
            is_checkbox: false,
            height: tableHeight,
            is_cache: false,
            is_click_icon: false,
            end: function (e) {
            },
            cols: [
                {
                    key: 'title',
                    title: '名称',
                    templet: function (r) {
                        return r.title.replace("$$", "<span style='font-weight: bold;font-size: 14px;'>").replace("$#", "</span>")
                    }
                }, {
                    title: '操作',
                    align: 'center',
                    width: 80, unresize: true,
                    templet: function (item) {
                        let r = item;
                        return "<a lay-filter='detail' onclick=\"detail('" + r.id + "')\">详情</a>";
                    }
                }
            ], done: function () {
                bindClick2();
            }
        });
    }

    function bindClick() {
        table.on("tool(control)", function (obj) {
            let data = obj.data;
            if (obj.event === "detail") {
                window.dataDetail = data;

                let time = $("#time").val();
                if (time === '') {
                    layer.msg('请选择起始时间!', {icon: 2});
                    return false;
                }
                let start, end;
                time = time.split(' - ');
                if (time != null && time.length === 2) {
                    start = time[0].replace(' ', 'T') + '.000Z';
                    end = time[1].replace(' ', 'T') + '.000Z';
                }

                let host = $("#host").val();
                let transactionResult = $("#transactionResult").val();
                let environment = $("#environment").val();

                let hosts = [];
                hosts.push(host);
                let transactionResults = [];
                transactionResults.push(transactionResult);
                let uiFilters = {
                    environment: environment
                };

                if (host !== '') {
                    uiFilters['host'] = hosts;
                }

                if (transactionResult !== '') {
                    uiFilters['transactionResult'] = transactionResults;
                }
                $.post({
                    url: '/services/distribution',
                    dataType: 'json',
                    data: {
                        start: encodeURIComponent(start),
                        end: encodeURIComponent(end),
                        uiFilters: encodeURIComponent(JSON.stringify(uiFilters)),
                        transactionName: encodeURIComponent(data.transactionName),
                        transactionType: data.transactionType,
                        serviceName: data.serviceName
                    },
                    success: function (res) {
                        let data = [];
                        if (res.success) {
                            if (res.data.buckets === '') {
                                data = [];
                            } else {
                                data = res.data.buckets;
                            }

                            let temp = '';
                            let count = 0;
                            if (data.length > 0) {
                                for (let i in data) {
                                    if (data.hasOwnProperty(i)) {
                                        temp = data[i]['samples'];
                                        if (temp === '') {
                                            continue;
                                        }
                                        if (temp.length > 0 && temp[0] !== undefined) {
                                            temp = temp[0]['traceId'];
                                            break;
                                        }
                                    }
                                }
                                for (let i in data) {
                                    if (data.hasOwnProperty(i)) {
                                        if (temp === '') {
                                            continue;
                                        }
                                        count += data[i]['count'];
                                    }
                                }
                            }
                            let errorCount = 0;
                            if (temp !== '') {
                                $.post({
                                    url: '/traces/listById',
                                    data: {
                                        start: encodeURIComponent(start),
                                        end: encodeURIComponent(end),
                                        traceId: temp
                                    },
                                    success: function (res) {
                                        data = [];
                                        if (res.success) {
                                            if (res.data.trace.items === '') {
                                                data = [];
                                            } else {
                                                data = res.data.trace.items;
                                                let ed = res.data.trace.errorDocs;
                                                if (ed !== undefined && ed.length > 0) {
                                                    errorCount = ed.length;
                                                }
                                            }
                                        }
                                        let rs = [];
                                        let services = '', ss = {};
                                        let useTime = 0;
                                        let allTime = 0;
                                        let allCount = 0;
                                        if (data.length > 0) {
                                            for (let i in data) {
                                                if (data.hasOwnProperty(i)) {
                                                    if (ss[data[i].service.name] === undefined) {
                                                        ss[data[i].service.name] = 1;
                                                        if (services === '') {
                                                            services = "<span class='layui-badge layui-bg-cyan'>" + data[i].service.name + "</span>";
                                                        } else {
                                                            services += "&nbsp;&nbsp;<span class='layui-badge layui-bg-cyan'>" + data[i].service.name + "</span>";
                                                        }
                                                    }
                                                    if (i <= 0) {
                                                        useTime = Number(Number(data[i]['transaction']['duration']['us']));
                                                        if (useTime / 1000 >= 1) {
                                                            useTime = (useTime / 1000).toFixed(0) + ' ms';
                                                        } else {
                                                            useTime += ' μs';
                                                        }
                                                        rs.push({
                                                            id: data[i]['transaction']['id'],
                                                            pid: '',
                                                            title: (data[i]['transaction']['result'] === undefined ? '' : data[i]['transaction']['result'] + ' ') + '$$' + data[i]['transaction']['name'] + '$# ' + useTime + ' （' + count + '）',
                                                            timestamp: data[i]['timestamp']['us'],
                                                            time: new Date(Number(fix(data[i]['timestamp']['us'] / 1000, 0))).format('yyyy-MM-dd hh:mm:ss.S')
                                                            , i: i
                                                            , data: data[i]
                                                            , transactionName: data[i]['transaction']['name']
                                                            , duration: useTime
                                                            , count: count
                                                        });
                                                        allTime = useTime;
                                                        allCount = count;
                                                    } else {
                                                        if (data[i]['span'] === undefined) {
                                                            useTime = Number(Number(data[i]['transaction']['duration']['us']));
                                                            if (useTime / 1000 >= 1) {
                                                                useTime = (useTime / 1000).toFixed(0) + ' ms';
                                                            } else {
                                                                useTime += ' μs';
                                                            }
                                                            rs.push({
                                                                id: data[i]['transaction']['id'],
                                                                pid: data[i]['parent']['id'],
                                                                title: (data[i]['transaction']['result'] === undefined ? '' : data[i]['transaction']['result'] + ' ') + '$$' + data[i]['transaction']['name'] + '$# ' + useTime,
                                                                timestamp: data[i]['timestamp']['us'],
                                                                time: new Date(Number(fix(data[i]['timestamp']['us'] / 1000, 0))).format('yyyy-MM-dd hh:mm:ss.S')
                                                                , i: i
                                                                , data: data[i]
                                                                , transactionName: data[i]['transaction']['name']
                                                                , duration: useTime,
                                                            });
                                                        } else {
                                                            useTime = Number(Number(data[i]['span']['duration']['us']));
                                                            if (useTime / 1000 >= 1) {
                                                                useTime = (useTime / 1000).toFixed(0) + ' ms';
                                                            } else {
                                                                useTime += ' μs';
                                                            }
                                                            rs.push({
                                                                id: data[i]['span']['id'],
                                                                pid: data[i]['parent']['id'],
                                                                title: data[i]['span']['name'] + ' ' + useTime,
                                                                timestamp: data[i]['timestamp']['us'],
                                                                time: new Date(Number(fix(data[i]['timestamp']['us'] / 1000, 0))).format('yyyy-MM-dd hh:mm:ss.S')
                                                                , i: i
                                                                , data: data[i]
                                                                , duration: useTime,
                                                            });
                                                        }
                                                    }
                                                }
                                            }
                                            //TODO:表格头部信息
                                            let method = '';
                                            if (data[0].http !== undefined && data[0].http.request !== undefined) {
                                                method = "<span class='layui-badge layui-bg-cyan'>" + data[0].http.request.method + "</span>";
                                            }
                                            let url = '';

                                            if (data[0]['url'] !== undefined && data[0]['url']['full'] !== undefined) {
                                                url = "<span class='layui-badge layui-bg-cyan'>地址</span> " + data[0]['url']['full'] + "<br/>";
                                            }
                                            errorCount = (errorCount > 0 ? "&nbsp;&nbsp;<span class='layui-badge layui-bg-red'>错误(" + errorCount + ")</span>" : '');
                                            allCount = "<span class='layui-badge layui-bg-cyan'>访问次数(" + allCount + ")</span>";
                                            $("#info").html(
                                                (method === '' ? '' : method + "&nbsp;&nbsp;")
                                                + (url === '' ? '' : url)
                                                // + "<span class='layui-badge layui-bg-cyan'>起始点</span> " + data[0]['event']['ingested'].replace('T', ' ').substring(0, 19)
                                                + "<span class='layui-badge layui-bg-cyan'>起始点</span> " + new Date(Number(fix(data[0]['timestamp']['us'] / 1000, 0))).format('yyyy-MM-dd hh:mm:ss.S')
                                                + "&nbsp;&nbsp;"
                                                + "<span class='layui-badge layui-bg-cyan'>持续时间</span> " + allTime
                                                + "&nbsp;&nbsp;"
                                                + allCount
                                                + errorCount
                                                + "<br/>"
                                                + services
                                            );

                                        }
                                        buildTable2(rs);
                                        return false;
                                    }
                                });
                            }
                        }
                        buildTable2([]);
                    }
                });
            }
        });
    }

    function detail(data) {
        let list = re.data;

        if (list !== null && list !== undefined && list.length > 0) {
            for (let i in list) {
                if (list.hasOwnProperty(i)) {
                    if (list[i]['id'] === data) {
                        data = list[i];
                        break;
                    }
                }
            }
        }

        // console.log(data);

        if (data.transactionName === undefined) {//需要取父级的名称.
            if (list !== null && list !== undefined && list.length > 0) {
                for (let i in list) {
                    if (list.hasOwnProperty(i)) {
                        if (list[i]['id'] === data.pid) {
                            if (list[i]['transactionName'] !== undefined && list[i]['transactionName'] !== '') {
                                data['transactionName'] = list[i]['transactionName'];
                            }
                            break;
                        }
                    }
                }
            }
        }

        sessionStorage.setItem("param", JSON.stringify(data));

        data = data.data;

        if (data.span !== undefined && data.span.stacktrace !== undefined && data.span.stacktrace.length > 0) {
            layer.open({
                title: ["详情", "font-weight:bold"],
                resize: true,
                type: 2,
                maxmin: true,
                shadeClose: true,
                area: ["666px", "100%"],
                content: "/toPage?name=/trace/traceDetail2"
            });
        } else {
            layer.open({
                title: ["详情", "font-weight:bold"],
                resize: true,
                type: 2,
                maxmin: true,
                shadeClose: true,
                area: ["777px", "100%"],
                content: "/toPage?name=/trace/traceDetail"
            });
        }


    }

    function bindClick2() {
        $('.open-all').click(function () {
            treeTable.openAll(re);
        })
    }

    function fix(num, decimal) {
        num = num.toString();
        let index = num.indexOf('.');
        if (index !== -1) {
            num = num.substring(0, decimal + index + 1)
        } else {
            num = num.substring(0)
        }
        return parseFloat(num).toFixed(decimal)
    }

    /**
     * 获取环境列表
     * @returns
     */
    function getEnv() {
        let time = $("#time").val();
        if (time === '') {
            layer.msg('请选择起始时间!', {icon: 2});
            return false;
        }
        let start, end;

        time = time.split(' - ');
        if (time != null && time.length === 2) {
            start = time[0].replace(' ', 'T') + '.000Z';
            end = time[1].replace(' ', 'T') + '.000Z';
        }
        $.post({
            url: '/services/getEnv',
            data: {
                start: encodeURIComponent(start),
                end: encodeURIComponent(end)
            },
            success: function (res) {
                console.log(res);
            }
        });
    }

    /**
     * 获取服务、探针列表
     */
    function getParam() {
        let time = $("#time").val();
        if (time === '') {
            return false;
        }
        let start, end;
        time = time.split(' - ');
        if (time != null && time.length === 2) {
            start = time[0].replace(' ', 'T') + '.000Z';
            end = time[1].replace(' ', 'T') + '.000Z';
        }
        let environment = $("#environment").val();
        let uiFilters = {environment: environment};

        $.post({
            url: '/services/getParam',
            data: {
                start: start,
                end: end,
                uiFilters: encodeURIComponent(JSON.stringify(uiFilters)),
                filterNames: encodeURIComponent('["host","transactionResult"]')
            },
            success: function (res) {
                if (res.success) {
                    let data = res.data;
                    $("#host").html("<option value=''>请选择服务主机名</option>");
                    $("#transactionResult").html("<option value=''>请选择交易结果</option>");
                    if (data.length > 0) {
                        for (let i in data) {
                            if (data.hasOwnProperty(i)) {
                                let temp = data[i];
                                let ops = temp['options'];
                                if (temp['name'] === 'host') {
                                    if (ops.length > 0) {
                                        for (let o in ops) {
                                            if (ops.hasOwnProperty(o)) {
                                                $("#host").append(new Option(ops[o]['name'] + "(" + ops[o]['count'] + ")", ops[o]['name']))
                                            }
                                        }
                                    }
                                }
                                if (temp['name'] === 'transactionResult') {
                                    if (ops.length > 0) {
                                        for (let o in ops) {
                                            if (ops.hasOwnProperty(o)) {
                                                $("#transactionResult").append(new Option(ops[o]['name'], ops[o]['name']))
                                                // $("#transactionResult").append(new Option(ops[o]['name'] + "(" + ops[o]['count'] + ")", ops[o]['name']))
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    layui.form.render();
                }
            }
        });
    }

    function init() {
        let ua = navigator.userAgent.toLowerCase();
        let screenWidth = window.screen.width;
        if (!/iphone|ipad|ipod/.test(ua)) {
            $("#iosiframe").attr("scrolling", "auto");
        } else {
            $('#iosiframe').width(screenWidth + 'px');
        }

        $("body").css({
            "height": $(window).height() - 15
        });
        $("#body_div").css({
            "height": $("body").height() - $("#head_div").height() - 10
        });
        tableHeight = $("#body_div").height() - 15;
    }

    layui.$(window).resize(function () {
        init();
    });
</script>
</body>
</html>
